#include "udpServer.hpp"
#include <memory>
#include <fstream>
#include <unordered_map>
#include <functional>
#include <signal.h>
#include "onlineUser.hpp"
using namespace std;
using namespace Server;
// const string dictTxt = "./dict.txt";
// unordered_map<string, string> dict;
static void Usage(string proc)
{
    cout << "\n Usage:\n\t" << proc << "local_port\n\n";
}
// ./udpServer port
// demo1 dict
// static bool cutString(const string &target, string *key, string *values, string sep)
// {
//     // apple:苹果
//     auto pos = target.find(sep);
//     if (pos == string::npos)
//     {
//         return false;
//     }
//     *key = target.substr(0, pos);
//     *values = target.substr(pos + 1);
//     return true;
// }
// static void initDict()
// {
//     ifstream in(dictTxt, std::ios::binary);
//     if (!in.is_open())
//     {
//         cerr << "open file" << dictTxt << "error" << endl;
//         exit(OPEN_ERR);
//     }
//     string line, key, values;
//     while (getline(in, line))
//     {
//         if (cutString(line, &key, &values, ":"))
//         {
//             dict.insert(make_pair(key, values));
//         }
//         // cout<<line<<endl;
//     }
//     in.close();
// }
// void reload(int signo)
// {
//     (void)signo;
//     initDict();
// }
// //demo1
// void handlerMessage(int sockfd, string clientip, uint16_t clientport, string message)
// {
//     string response_message;
//     initDict();
//     auto it = dict.find(message.c_str());
//     if (it == dict.end())
//         response_message = "unkonwn";
//     else
//         response_message = it->second;

//     // 开始返回
//     struct sockaddr_in client;
//     bzero(&client, sizeof client);
//     client.sin_family = AF_INET;
//     client.sin_port = htons(clientport);
//     client.sin_addr.s_addr = inet_addr(clientip.c_str());
//     sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr *)&client, sizeof client);
// }
// //demo2
// void execCommand(int sockfd, string clientip, uint16_t clientport, string cmd)
// {
//     if (cmd.find("rm") != string::npos || cmd.find("mv") != string::npos || cmd.find("rmdir") != string::npos)
//     {
//         cerr << clientip << ":" << clientport << " 正在做一个非法的操作: " << cmd << endl;
//         return;
//     }
//     string response;
//     FILE *fp = popen(cmd.c_str(), "r"); // pipe,fork,exec
//     if (fp == nullptr)
//         response = cmd + " exec failed";
//     char line[1024];
//     while (fgets(line, sizeof line, fp))
//         response += line;
//     pclose(fp);
//     // 开始返回
//     struct sockaddr_in client;
//     bzero(&client, sizeof client);
//     client.sin_family = AF_INET;
//     client.sin_port = htons(clientport);
//     client.sin_addr.s_addr = inet_addr(clientip.c_str());
//     sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr *)&client, sizeof client);
// }

// demo3
OnlineUser onlineuser;
void routeMessage(int sockfd, string clientip, uint16_t clientport, string message)
{
    if (message == "online")
        onlineuser.addUser(clientip, clientport);
    if(message == "offline")
        onlineuser.delUser(clientip, clientport);
    if (onlineuser.isOnline(clientip, clientport))
    {
        //消息的路由
        onlineuser.broadcastMessage(sockfd,clientip,clientport,message);
    }
    else
    {
        struct sockaddr_in client;
        bzero(&client, sizeof client);
        client.sin_family = AF_INET;
        client.sin_port = htons(clientport);
        client.sin_addr.s_addr = inet_addr(clientip.c_str());
        string response = "你还没有上线，请先上线，运行online";
        sendto(sockfd, response.c_str(), response.size(), 0, (struct sockaddr *)&client, sizeof client);
    }
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);
    // signal(2,reload);
    // std::unique_ptr<udpServer> usvr(new udpServer(handlerMessage, port));
    // std::unique_ptr<udpServer> usvr(new udpServer(execCommand, port));
    std::unique_ptr<udpServer> usvr(new udpServer(routeMessage, port));
    usvr->InitServer();
    usvr->start();
    return 0;
}
